/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.bincent.common.web;

import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;

import java.io.Serializable;

/**
 * description
 *
 * @author Matrix
 * @date 2020-07-08 11:24
 * @since 0.1.0
 */
public class Result<T> implements Serializable {
	private static final long serialVersionUID = 7838436396387981097L;
	/**
	 * 响应状态码
	 * 详细说明:https://fastapi.bincent.com/devote/standard/code.html
	 */
	private Integer code;
	/**
	 * 响应描述
	 */
	private String message;
	/**
	 * 响应时间戳
	 */
	private Long timestamp = System.currentTimeMillis();
	/**
	 * 操作成功的响应数据
	 */
	private T data;

	public Result() {
	}

	public Result(int code, String message, T data) {
		this.code = code;
		this.message = message;
		this.data = data;
	}

	public Integer getCode() {
		return code;
	}

	public void setCode(Integer code) {
		this.code = code;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public Long getTimestamp() {
		return timestamp;
	}

	public void setTimestamp(Long timestamp) {
		this.timestamp = timestamp;
	}


	public T getData() {
		return data;
	}

	public void setData(T data) {
		this.data = data;
	}

	public static Result success(Object data) {
		return new Result<>(200, "success", data);
	}

	public String toJson() throws Exception {
		return JacksonUtil.obj2json(this);
	}

	private static class JacksonUtil {
		private static final ObjectMapper OBJECT_MAPPER;

		static {
			OBJECT_MAPPER = JsonMapper.builder()
					.configure(JsonReadFeature.ALLOW_SINGLE_QUOTES, true)
					.configure(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS, true)
					.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
					.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true)
					.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
					.addModule(new ParameterNamesModule())
					.addModule(new Jdk8Module())
					.addModule(new JavaTimeModule())
					.build();
		}

		public static <T> String obj2json(T obj) throws Exception {
			return OBJECT_MAPPER.writeValueAsString(obj);
		}
	}
}
